By Monkeymatt last edited on Saturday, May 20, 2006 at 1:11:02 pm by Monkeymatt. Page
PHP Code
<?php
class Template{
// Define global variables
private $code=array(); // This will hold all of the code we get and all of the sections in a multidimensional array
private $file_root; // Holds the main directory where the template files are stored, defined in constructor
private $current_level=0; // Holds the current level in the level tracker (0 is the file, 1 and up are sections)
private $level_tracker=array(); // Holds a reference to the places in the main code array where we went through to get to where we are
private $current_item; // Holds a reference to the current place in the $code array
private $printed=false; // Whether we have given the output or not
// Generic error function to help make error reporting easier
protected function error($function, $message) {
die("<b>Error</b><br />Function: $function<br />Message:$message");
}
// Constructor, takes in file root and sets it in the global variable
public function __construct($file_root="./") {
if ($file_root == "") {
$file_root="./";
} else if (!is_dir($file_root)) {
$this->error("Constructor", "$file_root is not a directory"); // Throw an error if the directory does not exist
}
// Now there are no errors
$this->file_root=$file_root; // Set global variable
$this->code['base']['****code****']=''; // For later
}
// Adds files
public function add_file($file) {
if (!is_file($this->file_root.$file)) {
$this->error("add_file()", "File '$file' does not exist.");
}
$contents=file_get_contents($this->file_root.$file);
if (empty($contents)) {
$this->error("add_file()", "File '$file' is empty.");
} else {
$this->code['base']['****code****'].=$contents; // add $contents to the variable we initiated in the constructor
}
$this->level_tracker=array(); // clear of all other references because we started at the beginning again
$this->level_tracker[0]=&$this->code['base']; // Set bottom of level_tracker to be a reference to the base of the code array
$this->current_level=0;
$this->current_item=&$this->code['base']; // Current item is now the base of the code array, this variable can be used exactly the same as $level_tracker[0] right now
}
// Replaces references using __set special method (setting a variable calls this if the variable is not accessible to them)
// e.x. $template->java="fun"; -- $name=java, $value=fun
public function __set($name, $value) {
if (strpos($name, "base_") === 0) { // starts with 'base_', do whole section
$name=substr($name, 5); // remove 'base_' from the beginning
$this->level_tracker[0]['****code****']=str_replace("{".$name."}", $value, $this->level_tracker[0]['****code****']);
} else {
if ($this->current_level < 1) {
$this->error("value set", "No Section Set (Use 'base_' before the term to do it in the whole of the file)");
}
$num=$this->current_item['****current_iteration****']; // for below
if (empty($this->current_item[$num]['****code****'])) { // no code for current_item, so set it
$this->current_item[$num]['****code****']=$this->current_item['****code****'];
}
$this->current_item[$num]['****code****']=str_replace("{".$name."}", $value, $this->current_item[$num]['****code****']);
}
}
// Function to set section and extract code data from current item
public function set_section($section) {
if (empty($this->current_item)) {
$this->error("set_section()", "No handle set");
}
if (empty($section)) {
$this->error("set_section()", "No section given");
}
$found=false;
// Search down the level_tracker array until we find the requested section
for ($i=$this->current_level;$i>=0;$i--) {
$contents=array(); // For reg expression below
preg_match('|<{'.$section.'}>(.*)<{/'.$section.'}>|iUs', $this->level_tracker[$i]['****code****'], $contents);
if (!empty($contents[1])) { // If we found the section
$found=true;
if ($i == 0) {
$this->current_item=&$this->level_tracker[$i][$section]; // set current item reference
} else {
// If no current iteration for section we are taking this out of, make one
if (empty($this->level_tracker[$i][0]['****code****'])) {
$this->level_tracker[$i][0]['****code****']=$this->level_tracker[$i]['****code****'];
}
$num=$this->level_tracker[$i]['****current_iteration****']; // for below
$this->current_item=&$this->level_tracker[$i][$num][$section]; // set current item
}
$this->level_tracker[$i+1]=&$this->current_item; // add this to level_tracker
$this->current_level=$i+1; // update current level
if (empty($this->current_item['****code****'])) { // not exist yet, setup
$this->current_item['****code****']=$contents[1];
$this->current_item['****current_iteration****']=0;
}
break;
}
}
if (!$found) {
$this->error("set_section()", "No section found for '$section'");
}
}
// Go to next section iteration
public function next_section_iteration() {
$num=$this->current_item['****current_iteration****']; // get current number
if (empty($this->current_item[$num]['****code****'])) { // fill up current iteration if empty
$this->current_item[$num]['****code****']=$this->current_item['****code****'];
}
$this->current_item['****current_iteration****']++; // increase number
}
// Go through arrays and get them ready to print
// $array is the current array, $key is the name of the section, and $prev_array is the previous array (for setting code)
private function set_array_for_print(array &$array, $key, array &$prev_array) {
$final=''; // final code for the array
for ($i=0;$i<=$array['****current_iteration****'];$i++) { // go through all iterations of the array
if (!empty($array[$i])) {
if (is_array($array[$i])) {
foreach ($array[$i] as $key2=>&$value) { // inside 0-9 array keys
if ($key2 != '****code****') { // don't want to mess up ****code****
$this->set_array_for_print(&$value, $key2, &$array[$i]); // setup lower sections
}
}
$final.=$array[$i]['****code****']; // setup from previous $this->set_array_for_print()
}
}
}
// Replace section code in $code array with the final values for the loop
$prev_array['****code****']=preg_replace("|<{".$key."}>(.*)<{/".$key."}>|iUs", $final, $prev_array['****code****']);
}
// Gets the template ready to be printed
public function output() {
// go through the bottom of the level_tracker and start the recursive set_array_for_print function
foreach ($this->level_tracker[0] as $key=>&$value) {
if ($key != '****code****') { // only do it if not ****code**** (all others are real sections)
$this->set_array_for_print(&$value, $key, &$this->level_tracker[0]);
}
}
$this->printed=true; // set printed variable to say that it was printed
return $this->level_tracker[0]['****code****']; // return compiled code
}
// Destructs and prints out item
public function __destruct() {
if (!$this->printed) { // if not printed
echo $this->output(); // echo output
}
}
}
?>